package framework

import (
	"fmt"
	"html"
	"net/http"
	"strings"
)

type Core struct {
	router map[string]map[string]ControllerHandler
}

func NewCore() *Core {
	router := map[string]map[string]ControllerHandler{}
	router["GET"] = map[string]ControllerHandler{}
	router["POST"] = map[string]ControllerHandler{}
	router["PUT"] = map[string]ControllerHandler{}
	router["DELETE"] = map[string]ControllerHandler{}

	return &Core{router: router}
}

func (c *Core) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	fmt.Printf("Hello, %q\n", html.EscapeString(request.URL.Path))
	handler := c.findRouteByRequest(request)
	ctx := NewContext(request, response)
	if handler == nil {
		ctx.Json(404, "Not found.")
		return
	}

	if err := handler(ctx); err != nil {
		ctx.Json(500, "Internal error.")
		return
	}
}

func (c *Core) Get(url string, handler ControllerHandler) {
	c.router["GET"][strings.ToUpper(url)] = handler
}
func (c *Core) Post(url string, handler ControllerHandler) {
	c.router["POST"][strings.ToUpper(url)] = handler
}
func (c *Core) Put(url string, handler ControllerHandler) {
	c.router["PUT"][strings.ToUpper(url)] = handler
}
func (c *Core) Delete(url string, handler ControllerHandler) {
	c.router["DELETE"][strings.ToUpper(url)] = handler
}

func (c *Core) findRouteByRequest(request *http.Request) ControllerHandler {
	if handlers, ok := c.router[request.Method]; ok {
		if handler, ok := handlers[strings.ToUpper(request.URL.Path)]; ok {
			return handler
		}
	}
	return nil
}
